package jp.ac.u_tokyo.dch.service;

import java.util.List;
import java.util.Map;

import jp.ac.u_tokyo.dch.core.db.DBConnection;
import jp.ac.u_tokyo.dch.core.exceptions.DBException;
import jp.ac.u_tokyo.dch.dao.common.SeqenceGenerator;
import jp.ac.u_tokyo.dch.dao.front.DataDisplayDetailDao;
import jp.ac.u_tokyo.dch.dao.front.DataDisplaysDao;
import jp.ac.u_tokyo.dch.dao.front.FrontDisplayGroupDao;
import jp.ac.u_tokyo.dch.dao.front.GroupItemsDao;
import jp.ac.u_tokyo.dch.dao.schema.DataSchemaDao;
import jp.ac.u_tokyo.dch.dao.schema.DataSchemaDetailDao;
import jp.ac.u_tokyo.dch.model.SchemaGroup;
import jp.ac.u_tokyo.dch.model.db.DataDisplays;
import jp.ac.u_tokyo.dch.model.db.DataSchema;
import jp.ac.u_tokyo.dch.model.db.DataSchemaDetail;
import jp.ac.u_tokyo.dch.model.db.FrontDisplayGroup;
import jp.ac.u_tokyo.dch.model.db.GroupItems;
import jp.ac.u_tokyo.dch.model.xml.DisplayItem;
import jp.ac.u_tokyo.dch.model.xml.DisplayItems;
import jp.ac.u_tokyo.dch.model.xml.FrontInfo;
import jp.ac.u_tokyo.dch.model.xml.FrontItem;
import jp.ac.u_tokyo.dch.util.XmlCommonUtil;
import jp.ac.u_tokyo.dch.util.common.CommonUtil;
import jp.ac.u_tokyo.dch.view.Constants;
import jp.ac.u_tokyo.dch.view.front.FrontManageView;
import jp.ac.u_tokyo.dch.view.front.FrontTreeView;


/**
 * @version 1.1
 */
public class FrontService {

	/**
	* DBコネクションオブジェクト
	 */
	private DBConnection dbconn = null;

	/**
	 * オブジェクト生成者
	 * @param dbconn
	 */
	public FrontService(DBConnection dbconn){
		this.dbconn = dbconn;
	}

	public void orderChange(String id, String cmd) throws DBException {

		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		DataDisplays displays = dataDisplaysDao.selectById(id);

		Integer keyschemaId = displays.getKeyschemaId();
		Integer order = displays.getOrder();
		DataDisplays updateDisplays = null;

		if (Constants.UP.equals(cmd)) {

			updateDisplays = dataDisplaysDao.selectById(keyschemaId, order - 1);

			dataDisplaysDao.updateOrder(displays.getId(), order - 1);
			dataDisplaysDao.updateOrder(updateDisplays.getId(), order);

		} else {

			updateDisplays = dataDisplaysDao.selectById(keyschemaId, order + 1);

			if (updateDisplays != null) {
				dataDisplaysDao.updateOrder(displays.getId(), order + 1);
				dataDisplaysDao.updateOrder(updateDisplays.getId(), order);
			}
		}

	}

	public DataDisplays getDataDisplays(String displaysid) throws DBException {

		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		return dataDisplaysDao.selectById(displaysid);
	}

	/**
	 * データ名をチェックする
	 * @param view データモデル
	 * @return true:重複する名前がある、false:なし
	 * @throws DBException 例外
	 */
	public boolean checkName(FrontTreeView view)throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);

		return frontDisplayGroupDao.checkName(
				view.getFrontDisplayGroup().getDisplayName(), view.getFrontDisplayGroup().getId());
	}

	/**
	 * 資料データパターンリストを返す
	 * @return スキーマグループリスト
	 * @throws DBException 例外
	 */
	public List<SchemaGroup> getMetaDataPatternList() throws DBException {

		DataSchemaDao schemaDao = new DataSchemaDao(dbconn);

		return schemaDao.selectMetaDataPatternList();
	}

	/**
	 * データスキーマ詳細リストを取得する
	 * @return データスキーマ詳細リスト
	 * @throws DBException 例外
	 */
	public List<DataSchemaDetail> getCustomSchemaDataList() throws DBException {

		DataSchemaDetailDao schemaDetailDao = new DataSchemaDetailDao(dbconn);

		return schemaDetailDao.selectCustomList();
	}

	public List<DataDisplays> getDataDisplaysList(String keySchemaId) throws DBException {

		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		return dataDisplaysDao.selectByKeyId(keySchemaId);
	}

	/**
	 * データスキーマリストを取得する
	 * @return データスキーマリスト
	 * @throws DBException 例外
	 */
	public List<DataSchema> getFileSchemaDataList() throws DBException {

		DataSchemaDao schemaDao = new DataSchemaDao(dbconn);

		return schemaDao.selectList(Constants.LV7_SORT);
	}


	/**
	 * 挿入する
	 * @param keyschemaid キースキーマID
	 * @param frontInfo フロントオブジェクト
	 * @throws DBException 例外
	 */
	public void insert(FrontManageView view) throws DBException {

		SeqenceGenerator seqenceGenerator = new SeqenceGenerator(dbconn);
		DataDisplayDetailDao detailDao = new DataDisplayDetailDao(dbconn);
		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		String keySchemaId = view.getKeySchemaid();

		String displayName = view.getDisplayName();

		String frntXml = view.getFrntXML();

		FrontInfo frontInfo = XmlCommonUtil.xmlToObject(frntXml, FrontInfo.class);

		DataDisplays dataDisplays = new DataDisplays();

		dataDisplays.setKeyschemaId(Integer.valueOf(keySchemaId));
		dataDisplays.setName(displayName);

		int id = seqenceGenerator.getSequence(SeqenceGenerator.FRONT_DISPLAY_SEQ);

		dataDisplaysDao.insert(id, dataDisplays);

		detailDao.insert(id, frontInfo);

	}

	/**
	 * 挿入する
	 * @param keyschemaid キースキーマID
	 * @param frontInfo フロントオブジェクト
	 * @throws DBException 例外
	 */
	public void update(FrontManageView view) throws DBException {

		DataDisplayDetailDao detailDao = new DataDisplayDetailDao(dbconn);
		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		String keySchemaId = view.getKeySchemaid();

		String displayId = view.getDisplayId();

		String displayName = view.getDisplayName();

		String frntXml = view.getFrntXML();

		FrontInfo frontInfo = XmlCommonUtil.xmlToObject(frntXml, FrontInfo.class);

		DataDisplays dataDisplays = new DataDisplays();

		dataDisplays.setId(Integer.valueOf(displayId));
		dataDisplays.setKeyschemaId(Integer.valueOf(keySchemaId));
		dataDisplays.setName(displayName);

		dataDisplaysDao.update(dataDisplays);

		detailDao.delete(displayId);
		detailDao.insert(Integer.valueOf(displayId), frontInfo);

	}

	public void delete(String displayId) throws DBException {

		DataDisplayDetailDao detailDao = new DataDisplayDetailDao(dbconn);
		DataDisplaysDao dataDisplaysDao = new DataDisplaysDao(dbconn);

		dataDisplaysDao.delete(displayId);
		detailDao.delete(displayId);
	}

	/**
	 * フロント表示グループリストを取得する
	 * @return フロント表示グループリスト
	 * @throws DBException 例外
	 */
	public List<FrontDisplayGroup> getFrontDisplayGroupList()  throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);

		return frontDisplayGroupDao.selectList();
	}

	/**
	 *
	 * 挿入する
	 * @param view 画面モデル
	 * @throws DBException 例外
	 */
	public void insert(FrontTreeView view) throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);
		GroupItemsDao groupItemsDao = new GroupItemsDao(dbconn);
		SeqenceGenerator seqenceGenerator = new SeqenceGenerator(dbconn);

		int groupid = seqenceGenerator.getSequence(SeqenceGenerator.FRONT_DISPLAY_SEQ);

		FrontDisplayGroup displayGroup = view.getFrontDisplayGroup();
		Map<String, GroupItems> mapData = view.getDataMap();

		displayGroup.setId(String.valueOf(groupid));

		frontDisplayGroupDao.insert(displayGroup);
		groupItemsDao.insertAll(mapData.values(), groupid);
	}
	/**
	 * 削除する
	 * @param view 画面モデル
	 * @throws DBException 例外
	 */
	public void delete(FrontTreeView view) throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);
		GroupItemsDao groupItemsDao = new GroupItemsDao(dbconn);

		FrontDisplayGroup displayGroup = view.getFrontDisplayGroup();

		frontDisplayGroupDao.delete(displayGroup);
		groupItemsDao.deleteAll(Integer.valueOf(displayGroup.getId()));
	}
	/**
	 * 更新する
	 * @param view 画面モデル
	 * @throws DBException 例外
	 */
	public void update(FrontTreeView view) throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);
		GroupItemsDao groupItemsDao = new GroupItemsDao(dbconn);
		SeqenceGenerator seqenceGenerator = new SeqenceGenerator(dbconn);

		FrontDisplayGroup displayGroup = view.getFrontDisplayGroup();
		Map<String, GroupItems> mapData = view.getDataMap();

		frontDisplayGroupDao.delete(displayGroup);
		groupItemsDao.deleteAll(Integer.valueOf(displayGroup.getId()));

		int groupid = seqenceGenerator.getSequence(SeqenceGenerator.FRONT_DISPLAY_SEQ);

		displayGroup.setId(String.valueOf(groupid));
		frontDisplayGroupDao.insert(displayGroup);
		groupItemsDao.insertAll(mapData.values(), groupid);

	}

	/**
	 * フロントツリーモデルを設定する
	 * @param groupid グループID
	 * @param view 画面モデル
	 * @throws DBException 例外
	 */
	public void setOutputFrontTreeView(String groupid, FrontTreeView view) throws DBException {

		FrontDisplayGroupDao frontDisplayGroupDao = new FrontDisplayGroupDao(dbconn);
		GroupItemsDao groupItemsDao = new GroupItemsDao(dbconn);

		FrontDisplayGroup frontDisplayGroup = frontDisplayGroupDao.selectObject(groupid);
		List<GroupItems> list = groupItemsDao.selectList(groupid);

		view.setFrontDisplayGroup(frontDisplayGroup);
		view.setList(list);
	}


	/**
	 * フロント情報オブジェクトを取得する
	 * @param schemaid スキーマID
	 * @return フロント情報オブジェクト
	 * @throws DBException 例外
	 */
	public FrontInfo getFrontInfo(String displaysid) throws DBException {

		FrontInfo info = new FrontInfo();

		DataDisplayDetailDao dao = new DataDisplayDetailDao(dbconn);

		List<FrontItem> itemList = dao.selectByKeyId(displaysid);

		info.setList(itemList);

		return info;
	}

	/**
	 * FLEX側に渡すスキーマ項目を取得する
	 * @param schemaid スキーマID
	 * @return スキーマ項目情報
	 * @throws Exception 例外
	 */
	public DisplayItems getDisplayItemXml(String schemaid) throws Exception {

		DataSchemaDetailDao schemaDetailDao = new DataSchemaDetailDao(dbconn);

		DisplayItems items = new DisplayItems();

		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid, schemaid, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid, schemaid, "1"));

		return items;
	}

	/**
	 * FLEX側に渡すスキーマ項目を取得する
	 * @param schemaid1 スキーマID
	 * @param schemaid2 スキーマID
	 * @param schemaid3 スキーマID
	 * @param schemaid4 スキーマID
	 * @param schemaid5 スキーマID
	 * @param schemaid6 スキーマID
	 * @return スキーマ項目情報
	 * @throws Exception 例外
	 */
	public DisplayItems getDisplayItemXml(
			String schemaid1,
			String schemaid2,
			String schemaid3,
			String schemaid4,
			String schemaid5,
			String schemaid6) throws Exception {

		DataSchemaDetailDao schemaDetailDao = new DataSchemaDetailDao(dbconn);

		DisplayItems items = new DisplayItems();

		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid1, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid1, "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid2, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid2, "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid3, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid3, "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid4, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid4, "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid5, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid5, "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid6, "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(schemaid6, schemaid6, "1"));

		return items;
	}

	public DisplayItems getDisplayItemXmlByMetaData(String keySchemaid) throws DBException {

		DataSchemaDao dataSchemaDao = new DataSchemaDao(dbconn);

		DataSchemaDetailDao schemaDetailDao = new DataSchemaDetailDao(dbconn);

		SchemaGroup schemaGroup = dataSchemaDao.selectMetaDataPattern(keySchemaid);

		DisplayItems items = new DisplayItems();

		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv1Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv1Schemaid(), "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv2Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv2Schemaid(), "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv3Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv3Schemaid(), "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv4Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv4Schemaid(), "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv5Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv5Schemaid(), "1"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv6Schemaid(), "0"));
		addItems(items, schemaDetailDao.selectListMinusDisplay(keySchemaid, schemaGroup.getLv6Schemaid(), "1"));


		return items;
	}

	private void addItems(DisplayItems items, List<DataSchemaDetail> list) {

		for (DataSchemaDetail detail : list) {

			DisplayItem item = new DisplayItem();
			item.setName(detail.getFieldDisplayname());
			setSortName(item, detail.getSort());
			item.setKey(detail.getFieldKey());
			item.setSchemaid(detail.getSchemaid());
			items.addDisplayItem(item);
		}
	}

	/**
	 *
	 * @param item
	 * @param sort
	 */
	private void setSortName(DisplayItem item, String sort) {
		item.setCategory(CommonUtil.getSortName(sort));
	}


}
